//
// Ephi - simulation of magnetic fields and particles
// Copyright (C) 2007 Indrek Mandre <indrek(at)mare.ee>
// For more information please see http://www.mare.ee/indrek/ephi/
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include "ephi.hpp"

#include <string>

// compare different interpolation techniques visually

#define RADIUS 0.15
#define WR 0.04

static bool calibrate = true;
static prec_t cali_e_min, cali_e_max;
static prec_t cali_b_min, cali_b_max;

static void calcsome (const std::string& prefix, const CoilData& cd, Statics& statics, ElectroDynamics& dyn)
{
  for ( int i = 0; i < 2; i++ )
    {
      Screen screen(i ? 340 : 800, i ? 340 : 800, RADIUS * 4, RADIUS * 4);
      Scene scene(dyn);

      std::string bn = prefix;
      if ( i ) bn = "snap_" + prefix;

      {
        scene.calc (screen, Scene::CALC_EFIELD);
        if ( calibrate )
          {
            cali_e_min = scene.get_fmin();
            cali_e_max = scene.get_fmax();
          }
        else
          {
            scene.calibrate_field (cali_e_min, cali_e_max);
          }

        scene.set_coloring (0);
        scene.render_map (screen);
        screen.write (bn + "_e.bmp");

        scene.set_coloring (32, true);
        scene.render_map (screen);
        screen.write (bn + "_e_log.bmp");

        scene.set_coloring (0, true);
        scene.render_lic (screen);
        screen.write (bn + "_e_lic_logcolor.bmp");
      }

      {
        scene.calc (screen);
        if ( calibrate )
          {
            cali_b_min = scene.get_fmin();
            cali_b_max = scene.get_fmax();
          }
        else
          {
            scene.calibrate_field (cali_b_min, cali_b_max);
          }

        scene.set_coloring (0);
        scene.render_map (screen);
        screen.write (bn + "_b.bmp");

        scene.set_coloring (32, true);
        scene.render_map (screen);
        screen.write (bn + "_b_log.bmp");

        scene.set_coloring (0, true);
        scene.render_lic (screen);
        screen.write (bn + "_b_lic_logcolor.bmp");
      }
      calibrate = false;
    }
}

int main (int argc, char *argv[])
{
  CoilGen cgen;
  cgen.radius = 0.15;
  cgen.wr = 0.04;
  cgen.do_efield = true;
  cgen.geom_radial = 0.30;
  cgen.geom_axial = 0.30;
  cgen.coil_matrix_n = 1;
  cgen.force_grid = 10;
  cgen.generate ("ivis.cgen");
  cgen.do_cubic = true;
  cgen.generate ("ivis3.cgen");

  CoilData cd, cd3;
  if ( !cd.load ("ivis.cgen") )
    {
      fprintf (stderr, "%s: failed to load ivis.cgen!\n", argv[0]);
      exit(-1);
    }
  if ( !cd3.load ("ivis3.cgen") )
    {
      fprintf (stderr, "%s: failed to load ivis3.cgen!\n", argv[0]);
      exit(-1);
    }

  {
    Statics statics;
    ElectroDynamics dyn(statics);
    ShapedCoilFactory().make (statics, vect3d(0, 0, 0), vect3d(1, 0, 0), RADIUS, WR, 1, 1e-7);
    calcsome ("ivis_dc", cd, statics, dyn);
  }

  {
    Statics statics;
    ElectroDynamics dyn(statics);
    statics.addStaticElement (new StaticCIL(cd, vect3d(0, 0, 0), vect3d(1, 0, 0), 1, 1e-7));
    calcsome ("ivis_li", cd, statics, dyn);
  }

  {
    Statics statics;
    ElectroDynamics dyn(statics);
    statics.addStaticElement (new StaticCINN(cd, vect3d(0, 0, 0), vect3d(1, 0, 0), 1, 1e-7));
    calcsome ("ivis_nn", cd, statics, dyn);
  }

  {
    Statics statics;
    ElectroDynamics dyn(statics);
    statics.addStaticElement (new StaticCICU(cd3, vect3d(0, 0, 0), vect3d(1, 0, 0), 1, 1e-7));
    calcsome ("ivis_cu", cd, statics, dyn);
  }

  remove ("ivis.cgen");
  remove ("ivis3.cgen");
  return 0;
}

